﻿using System;
using Caliburn.Micro;

namespace OPSYS_Schematic.UIInfrastructure
{
    /// <summary>
    /// Base <see cref="IPart"/> class for various implementations of <see cref="IPart"/>.
    /// </summary>
    public abstract class PartBase : PropertyChangedBase, IPart
    {
        private string displayName;
        private string icon;
        private string inputGestureText;
        private bool isVisible = true;
        private string name;

        protected PartBase()
            : this(null)
        {
        }

        protected PartBase(string name)
        {
            Name = name ?? GetType().Name.Replace("Part", string.Empty);
            execute = ((i) => { });
            canExecute = (() => IsActive);

            this.AutoUpdate(true);
            //修改 by YAY
            Icon = ImageFindHelper.FindIconPathByName("BrownLarge.png");
            EventAggregator = IoC.GetInstance(typeof (IEventAggregator), null) as IEventAggregator;
        }

        public PartBase(string name, Action<PartBase> execute, Func<bool> canExecute = null)
            : this(name)
        {
            this.execute = execute ?? ((i) => { });
            this.canExecute = canExecute ?? (() => IsActive);
        }

        /// <summary>
        /// 事件管理器,用于事件通知
        /// </summary>
        public IEventAggregator EventAggregator { get; private set; }

        #region IPart Members

        public string Name
        {
            get { return name; }
            protected set
            {
                name = value;
                NotifyOfPropertyChange(() => Name);
            }
        }

        public string DisplayName
        {
            get { return displayName; }
            set
            {
                displayName = value;
                NotifyOfPropertyChange(() => DisplayName);
            }
        }

        public string Icon
        {
            get { return icon; }
            set
            {
                icon = value;
                NotifyOfPropertyChange(() => Icon);
            }
        }

        public string InputGestureText
        {
            get { return inputGestureText; }
            set
            {
                inputGestureText = value;
                NotifyOfPropertyChange(() => InputGestureText);
            }
        }

        public bool IsVisible
        {
            get { return isVisible; }
            set
            {
                isVisible = value;
                NotifyOfPropertyChange(() => IsVisible);
            }
        }

        public virtual void OnAttached()
        {
        }

        public void Handle(LanguageChangedMessage message)
        {
            this.UpdateDisplayName();
        }

        #endregion

        #region IExecutable

        private readonly Func<bool> canExecute;
        private readonly Action<PartBase> execute;

        /// <summary>
        /// The action associated to the ActionItem
        /// </summary>
        public virtual void Execute()
        {
            execute(this);
        }

        /// <summary>
        /// Calls the underlying canExecute function.
        /// </summary>
        public virtual bool CanExecute
        {
            get { return canExecute(); }
        }

        #endregion

        #region Activation & Deactivation

        private bool isActive = true;
        public event EventHandler<ActivationEventArgs> Activated;
        public event EventHandler<DeactivationEventArgs> AttemptingDeactivation;
        public event EventHandler<DeactivationEventArgs> Deactivated;

        public bool IsActive
        {
            get { return isActive; }
        }

        public void Activate()
        {
            if (IsActive)
                return;

            isActive = true;
            OnActivate();
            if (Activated != null)
                Activated(this, new ActivationEventArgs {WasInitialized = false});
            NotifyOfPropertyChange(() => CanExecute);
        }

        public virtual void Deactivate(bool close)
        {
            if (!IsActive)
                return;

            if (AttemptingDeactivation != null)
                AttemptingDeactivation(this, new DeactivationEventArgs {WasClosed = close});

            isActive = false;
            OnDeactivate(close);
            NotifyOfPropertyChange(() => CanExecute);
            if (Deactivated != null)
                Deactivated(this, new DeactivationEventArgs {WasClosed = close});
        }

        protected virtual void OnActivate()
        {
        }

        protected virtual void OnDeactivate(bool close)
        {
        }

        #endregion
    }
}